import subprocess
import threading
import time
import os
import signal
from typing import Dict, Optional, Tuple, List
from .process_state import ProcessState, ProcessInfo, SystemState
from config_loader import config_loader
from logger.process_logger import process_logger


class StateManager:
    def __init__(self):
        self.processes: Dict[str, ProcessInfo] = {}
        self.system_state = SystemState()
        self.lock = threading.RLock()

        # 从配置文件加载
        self.config = config_loader
        self.resource_names = self.config.get_resource_names()
        self.exclusive_indices = self.config.get_exclusive_resource_indices()

        # 记录系统启动
        process_logger.log_system_startup()

        print(f"资源名称: {self.resource_names}")
        print(f"独占资源索引: {self.exclusive_indices}")
        print(f"锁类型: {type(self.lock)}")

        self._register_processes()

    def _register_processes(self):
        """从配置文件注册所有启用的进程"""
        enabled_processes = self.config.get_enabled_processes()

        for name, config in enabled_processes.items():
            self.processes[name] = ProcessInfo(
                name=name,
                command=config['command'],
                state=ProcessState.STOPPED,
                resources=config['resources'],
                display_name=config.get('display_name', name),
                description=config.get('description', '')
            )

        print(f"已注册 {len(self.processes)} 个进程")
        process_logger.log_config_loaded(len(self.processes))

    def get_system_state(self) -> Dict:
        """获取系统状态"""
        resource_usage = self.system_state.get_resource_usage()
        resource_conflicts = self.system_state.get_resource_conflicts()

        # 构建资源状态信息
        resource_status = {}
        for i, name in enumerate(self.resource_names):
            processes = list(resource_conflicts[i]) if i in resource_conflicts else []
            resource_status[name] = {
                'usage_count': resource_usage[i],
                'occupied_by': processes,
                'type': self.config.resources[name]['type']
            }

        return {
            'resource_usage': resource_usage,
            'resource_status': resource_status
        }

    def get_process_state(self, name: str) -> Optional[ProcessState]:
        """获取进程状态"""
        with self.lock:
            if name in self.processes:
                return self.processes[name].state
            return None

    def get_all_processes_status(self) -> Dict[str, dict]:
        """获取所有进程状态"""
        with self.lock:
            status = {}
            for name, info in self.processes.items():
                status[name] = {
                    "state": info.state.value,
                    "resources": info.resources,
                    "pid": info.pid,
                    "display_name": info.display_name,
                    "description": info.description
                }
            return status

    def can_start_process(self, name: str) -> Tuple[bool, str]:
        """检查是否可以启动进程"""
        with self.lock:
            if name not in self.processes:
                return False, f"进程 {name} 不存在"

            process_info = self.processes[name]

            # 检查进程当前状态
            if process_info.state != ProcessState.STOPPED:
                return False, f"进程 {name} 当前状态: {process_info.state.value}"

            # 检查资源冲突
            can_start, conflict_msg = self.system_state.check_resource_conflict(
                name, process_info.resources, self.exclusive_indices
            )

            if not can_start:
                return False, conflict_msg

            return True, "可以启动"

    def can_stop_process(self, name: str) -> Tuple[bool, str]:
        """检查是否可以停止进程"""
        with self.lock:
            if name not in self.processes:
                return False, f"进程 {name} 不存在"

            process_info = self.processes[name]

            if process_info.state != ProcessState.RUNNING:
                return False, f"进程 {name} 当前状态: {process_info.state.value}，无法停止"

            return True, "可以停止"

    def start_process(self, name: str) -> Tuple[bool, str]:
        """启动进程"""
        can_start, message = self.can_start_process(name)
        if not can_start:
            if "资源冲突" in message:
                process_logger.log_resource_conflict(name, message)
            else:
                process_logger.log_process_start_failed(name, message)
            return False, message

        with self.lock:
            process_info = self.processes[name]

            working_dir = "/root/yahboomcar_ros2_ws/yahboomcar_ws"

            # 记录启动尝试
            process_logger.log_process_start_attempt(name, process_info.display_name)

            # 获取系统配置
            startup_wait = self.config.system.get('default_startup_wait', 3)

            process_info.state = ProcessState.STARTING

            try:
                # 启动进程，创建新的进程组
                process = subprocess.Popen(
                    process_info.command,
                    stdout=subprocess.PIPE,
                    stderr=subprocess.STDOUT,
                    text=True,
                    bufsize=1,
                    universal_newlines=True,
                    preexec_fn=os.setsid,  # 创建新的进程组
                    cwd=working_dir  # 设置工作目录
                )

                process_info.process = process
                process_info.pid = process.pid

                # 等待进程初始化
                time.sleep(startup_wait)

                # 检查进程状态
                if process.poll() is None:
                    # 进程还在运行，启动成功
                    process_info.state = ProcessState.RUNNING

                    # 更新系统资源状态
                    self.system_state.add_process_resources(name, process_info.resources)

                    # 记录启动成功
                    process_logger.log_process_start_success(name, process.pid, process_info.resources)

                    return True, f"进程 {name} 启动成功，PID: {process.pid}"
                else:
                    # 进程已经退出，启动失败
                    process_info.state = ProcessState.FAILED
                    process_info.process = None
                    process_info.pid = None

                    reason = f"启动后立即退出，退出码: {process.returncode}"
                    process_logger.log_process_start_failed(name, reason)

                    return False, f"进程 {name} {reason}"

            except Exception as e:
                process_info.state = ProcessState.FAILED
                process_info.process = None
                process_info.pid = None

                process_logger.log_process_start_failed(name, str(e))
                return False, f"启动进程 {name} 失败: {str(e)}"

    def stop_process(self, name: str) -> Tuple[bool, str]:
        """停止进程"""
        can_stop, message = self.can_stop_process(name)
        if not can_stop:
            process_logger.log_process_stop_failed(name, message)
            return False, message

        with self.lock:
            process_info = self.processes[name]

            # 记录停止尝试
            process_logger.log_process_stop_attempt(name)

            # 获取系统配置
            shutdown_timeout = self.config.system.get('default_shutdown_timeout', 8)

            process_info.state = ProcessState.STOPPING

            try:
                if not process_info.process:
                    # 没有进程对象，直接标记为停止
                    process_info.state = ProcessState.STOPPED
                    self.system_state.remove_process_resources(name, process_info.resources)

                    process_logger.log_process_stop_success(name)
                    return True, f"进程 {name} 已停止"

                # 检查进程是否还在运行
                if process_info.process.poll() is not None:
                    # 进程已经结束
                    process_info.state = ProcessState.STOPPED
                    process_info.process = None
                    process_info.pid = None

                    self.system_state.remove_process_resources(name, process_info.resources)

                    process_logger.log_process_stop_success(name)
                    return True, f"进程 {name} 已经结束"

                # 进程还在运行，需要停止
                pid = process_info.process.pid
                print(f"🔍 准备停止进程，PID: {pid}")

                try:
                    # 检查进程组
                    try:
                        pgid = os.getpgid(pid)
                        print(f"🔍 进程组ID: {pgid}")
                    except OSError as e:
                        print(f"❌ 获取进程组失败: {e}")
                        # 如果获取进程组失败，直接对进程发送信号
                        process_info.process.send_signal(signal.SIGINT)
                        print(f"📤 直接向进程 {pid} 发送 SIGINT")
                    else:
                        # 第一步：发送 SIGINT 到进程组
                        print(f"📤 发送 SIGINT 信号到进程组 {pgid}")
                        os.killpg(pgid, signal.SIGINT)

                    # 等待进程响应SIGINT
                    sigint_timeout = 20
                    print(f"⏳ 等待进程退出，超时时间: {sigint_timeout}秒")

                    try:
                        start_time = time.time()
                        process_info.process.wait(timeout=sigint_timeout)
                        actual_time = time.time() - start_time

                        print(f"✅ 进程在 {actual_time:.2f}秒内退出")

                        # SIGINT成功，进程优雅退出
                        process_info.state = ProcessState.STOPPED
                        process_info.process = None
                        process_info.pid = None

                        self.system_state.remove_process_resources(name, process_info.resources)

                        process_logger.log_process_stop_success(name, "graceful_interrupt")
                        return True, f"进程 {name} 优雅停止成功 (SIGINT, {actual_time:.2f}s)"

                    except subprocess.TimeoutExpired:
                        print(f"⏰ SIGINT {sigint_timeout}秒超时，尝试SIGTERM")

                        # SIGINT超时，尝试SIGTERM
                        try:
                            pgid = os.getpgid(pid)
                            os.killpg(pgid, signal.SIGTERM)
                            print(f"📤 发送 SIGTERM 信号到进程组 {pgid}")
                        except OSError as e:
                            print(f"❌ SIGTERM发送失败: {e}")
                            process_info.process.terminate()
                            print(f"📤 直接terminate进程 {pid}")

                        # 等待SIGTERM响应
                        sigterm_timeout = 5
                        try:
                            start_time = time.time()
                            process_info.process.wait(timeout=sigterm_timeout)
                            actual_time = time.time() - start_time

                            print(f"✅ 进程响应SIGTERM退出，耗时: {actual_time:.2f}秒")

                            process_info.state = ProcessState.STOPPED
                            process_info.process = None
                            process_info.pid = None
                            self.system_state.remove_process_resources(name, process_info.resources)

                            process_logger.log_process_stop_success(name, "graceful_term")
                            return True, f"进程 {name} 停止成功 (SIGTERM)"

                        except subprocess.TimeoutExpired:
                            print(f"⏰ SIGTERM {sigterm_timeout}秒超时，强制KILL")

                            # SIGTERM也超时，最后使用SIGKILL强制终止
                            try:
                                pgid = os.getpgid(pid)
                                os.killpg(pgid, signal.SIGKILL)
                                print(f"💀 发送 SIGKILL 信号到进程组 {pgid}")
                            except OSError as e:
                                print(f"❌ SIGKILL发送失败: {e}")
                                process_info.process.kill()
                                print(f"💀 直接kill进程 {pid}")

                            try:
                                process_info.process.wait(timeout=5)
                                print(f"✅ 进程被强制终止")
                            except:
                                print(f"❌ 进程强制终止可能失败")

                            process_info.state = ProcessState.STOPPED
                            process_info.process = None
                            process_info.pid = None
                            self.system_state.remove_process_resources(name, process_info.resources)

                            process_logger.log_process_stop_success(name, "forced")
                            return True, f"进程 {name} 强制停止成功 (SIGKILL)"

                except ProcessLookupError as e:
                    print(f"🔍 进程查找错误: {e}")
                    # 进程已经不存在
                    process_info.state = ProcessState.STOPPED
                    process_info.process = None
                    process_info.pid = None
                    self.system_state.remove_process_resources(name, process_info.resources)

                    process_logger.log_process_stop_success(name, "already_dead")
                    return True, f"进程 {name} 已停止（进程不存在）"

            except Exception as e:
                print(f"❌ 停止过程发生未知异常: {e}")
                print(f"❌ 异常类型: {type(e)}")
                import traceback
                traceback.print_exc()

                # 停止过程中出现异常，尝试强制清理
                try:
                    if process_info.process and process_info.process.poll() is None:
                        print(f"❌ 异常情况，强制kill进程 {process_info.process.pid}")
                        process_info.process.kill()
                        process_info.process.wait(timeout=5)
                except Exception as cleanup_e:
                    print(f"❌ 清理过程也失败: {cleanup_e}")

                process_info.state = ProcessState.FAILED
                process_logger.log_process_stop_failed(name, str(e))
                return False, f"停止进程 {name} 失败: {str(e)}"

    def check_process_health(self, name: str) -> Tuple[bool, str]:
        """检查进程健康状态"""
        with self.lock:
            if name not in self.processes:
                return False, f"进程 {name} 不存在"

            process_info = self.processes[name]

            if process_info.state != ProcessState.RUNNING:
                return True, f"进程 {name} 状态: {process_info.state.value}"

            if not process_info.process:
                # 状态不一致，修复状态
                process_info.state = ProcessState.STOPPED
                self.system_state.remove_process_resources(name, process_info.resources)
                return False, f"进程 {name} 状态不一致，已修复为STOPPED"

            # 检查进程是否还在运行
            if process_info.process.poll() is None:
                return True, f"进程 {name} 运行正常"
            else:
                # 进程意外退出，更新状态
                exit_code = process_info.process.returncode
                process_info.state = ProcessState.STOPPED
                process_info.process = None
                process_info.pid = None

                self.system_state.remove_process_resources(name, process_info.resources)

                return False, f"进程 {name} 意外退出，退出码: {exit_code}"

    def check_all_processes_health(self) -> Dict[str, Tuple[bool, str]]:
        """检查所有进程健康状态"""
        health_status = {}
        for name in self.processes:
            health_status[name] = self.check_process_health(name)
        return health_status

    def get_resource_conflicts_info(self) -> Dict[str, List[str]]:
        """获取详细的资源冲突信息"""
        conflicts = self.system_state.get_resource_conflicts()
        result = {}

        for i, name in enumerate(self.resource_names):
            if i in conflicts and conflicts[i]:
                result[name] = list(conflicts[i])

        return result

    def get_process_config_info(self) -> Dict[str, dict]:
        """获取进程配置信息"""
        result = {}
        for name, process_info in self.processes.items():
            config = self.config.processes[name]
            result[name] = {
                'display_name': process_info.display_name,
                'description': process_info.description,
                'resources': process_info.resources,
                'enabled': config.get('enabled', True),
                'command': process_info.command
            }
        return result
